package com.unidt.www.framework.common.util.object;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.unidt.www.framework.common.util.object.annotation.BeanField;
import com.unidt.www.framework.common.util.object.annotation.NotBind;
import com.unidt.www.framework.common.util.object.plug.TableData;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

/**
 * 功能描述
 *
 * @author ZKJ
 * @date 2021/6/16
 */
public class BeanMapUtils {


    public static Long getId(Object obj, String key) {
        try {
            Class cls = obj.getClass();

            Field field = cls.getDeclaredField(key);
            field.setAccessible(true);
            Object s = field.get(obj);
            if (Objects.nonNull(s)) {
                return Long.valueOf(s.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;

    }

    public static Object getValue(Object obj, String key) {
        try {
            Class cls = obj.getClass();

            Field field = cls.getDeclaredField(key);
            field.setAccessible(true);
            Object s = field.get(obj);
            return s;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;

    }


    public static void setValue(Object obj, String key, Object value) {
        try {
            Class cls = obj.getClass();

            Field field = cls.getDeclaredField(key);
            if (Objects.nonNull(field)) {
                field.setAccessible(true);
                if (field.getType() == Integer.class) {
                    field.set(obj, Integer.valueOf(value.toString()));
                } else if (field.getType() == Double.class) {
                    field.set(obj, Double.valueOf(value.toString()));
                } else {
                    field.set(obj, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static Map<String, Object> toMap(Object obj) {
        HashMap map = new HashMap();

        try {
            if (obj == null) {
                return map;
            }

            Class cls = obj.getClass();
            Field[] fields = cls.getDeclaredFields();
            Field[] var4 = fields;
            int var5 = fields.length;

            for (int var6 = 0; var6 < var5; ++var6) {
                Field f = var4[var6];
                f.setAccessible(true);
                String fileName = f.getName();
                NotBind notBind = (NotBind) f.getAnnotation(NotBind.class);
                if (notBind == null) {
                    Class fileType = f.getType();
                    Object value = f.get(obj);

                    if (fileType == Date.class) {
                        if (Objects.nonNull(value)) {
                            map.put(fileName, DateUtil.formatDateTime((Date) value));
                        }
                    } else {
                        map.put(fileName, value);
                    }

                }
            }
        } catch (Exception var12) {
            var12.printStackTrace();
        }

        return map;
    }


    public static <T> T mapToBean(Map<String, String> map, Class cls) {
        try {
            if (map != null) {
                Constructor<?> cons = cls.getConstructor();
                Object obj = cons.newInstance();
                Field[] fields = cls.getDeclaredFields();
                Field[] var5 = fields;
                int var6 = fields.length;

                for (int var7 = 0; var7 < var6; ++var7) {
                    Field f = var5[var7];
                    String fileName = f.getName();
                    String value = (String) map.get(fileName);
                    if (value != null) {
                        Class typeClass = f.getType();
                        f.setAccessible(true);
                        if (typeClass.equals(Long.class)) {
                            f.set(obj, Long.parseLong(value));
                        } else if (typeClass.equals(Integer.class)) {
                            f.set(obj, Integer.parseInt(value));
                        } else if (typeClass.equals(Double.class)) {
                            f.set(obj, Double.parseDouble(value));
                        } else if (typeClass.equals(String.class)) {
                            f.set(obj, value);
                        }
                    }
                }

                return (T) obj;
            }
        } catch (Exception var12) {
            var12.printStackTrace();
        }

        return null;
    }


    /**
     * 功能描述: 判断该区域是否
     *
     * @param cls
     * @param filedName
     * @return boolean
     * @author zkj
     * @date 2021/11/23
     */

    public static boolean isNumeric(Class cls, String filedName) {

        try {
            Field field = cls.getDeclaredField(filedName);
            String typeName = field.getType().getName();
            if (typeName.equals(Integer.class.getName()) || typeName.equals(int.class.getName())) {
                return true;
            } else if (typeName.equals(Double.class.getName()) || typeName.equals(float.class.getName())) {
                return true;
            } else if (typeName.equals(Long.class.getName()) || typeName.equals(long.class.getName())) {
                return true;
            } else if (typeName.equals(BigDecimal.class.getName())) {
                return true;
            }
        } catch (Exception e) {

        }
        return false;
    }

    /**
     * 功能描述: 追加排名
     *
     * @param data
     * @param key
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @author zkj
     * @date 2021/11/26
     */

    public static List<Map<String, Object>> appendRankNoToList(List data, String key) {

        List<Map<String, Object>> dataList = new ArrayList<>();
        Integer rankNo = 0;
        Object lastVObj = new Object();
        for (int i = 0; i < data.size(); i++) {
            Object d = data.get(i);

            Map<String, Object> m = BeanMapUtils.toMap(d);
            Object fieldValue = BeanMapUtils.getValue(d, key);
            if (!lastVObj.equals(fieldValue)) {
                rankNo = i + 1;
            }
            m.put("rankNo", rankNo);

            lastVObj = fieldValue;
            dataList.add(m);
        }
        return dataList;
    }


    /**
     * 功能描述: 将list转化map为简单对象并追加rankNo
     *
     * @param data
     * @param key
     * @param orgNameKey
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @author zkj
     * @date 2021/11/30
     */

    public static List<Map<String, Object>> transForSampleData(List data, String key, String orgNameKey) {

        List<Map<String, Object>> dataList = new ArrayList<>();
        Integer rankNo = 0;
        Object lastVObj = new Object();
        for (int i = 0; i < data.size(); i++) {
            Object d = data.get(i);

            Map<String, Object> m = new HashMap<>();

            Object fieldValue = BeanMapUtils.getValue(d, key);

            Object orgName = BeanMapUtils.getValue(d, orgNameKey);

            if (!lastVObj.equals(fieldValue)) {
                rankNo = i + 1;
            }
            m.put("rankNo", rankNo);
            m.put("fieldValue", fieldValue);
            m.put("orgName", orgName);
            if (Objects.isNull(fieldValue)) {
                lastVObj = "";
            } else {
                lastVObj = fieldValue;
            }
            dataList.add(m);
        }
        return dataList;
    }


    public static List<Map<String, Object>> transForSampleDataMap(List<Map<String, Object>> data, String key, String orgNameKey) {

        List<Map<String, Object>> dataList = new ArrayList<>();
        Integer rankNo = 0;
        Object lastVObj = new Object();
        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> d = data.get(i);
            if (!d.containsKey(key)) {

                continue;
            }
            Object fieldValue = d.get(key);

            Map<String, Object> m = new HashMap<>();


            Object orgName = d.get(orgNameKey);

            if (!lastVObj.equals(fieldValue)) {
                rankNo = i + 1;
            }
            m.put("rankNo", rankNo);
            m.put("fieldValue", fieldValue);
            m.put("orgName", orgName);
            lastVObj = fieldValue;
            dataList.add(m);
        }
        return dataList;
    }


    public static List<Map<String, Object>> transForSampleDataMap(List<Map<String, Object>> data, String key,
                                                                  String orgNameKey, String targetOrgName) {

        List<Map<String, Object>> dataList = new ArrayList<>();
        Integer rankNo = 0;
        Object lastVObj = new Object();
        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> d = data.get(i);
            if (!d.containsKey(key)) {

                continue;
            }
            Object fieldValue = d.get(key);

            Map<String, Object> m = new HashMap<>();


            Object orgName = d.get(orgNameKey);

            if (!lastVObj.equals(fieldValue)) {
                rankNo = i + 1;
            }
            m.put("rankNo", rankNo);
            m.put("fieldValue", fieldValue);
            m.put(targetOrgName, orgName);
            lastVObj = fieldValue;
            dataList.add(m);
        }
        return dataList;
    }

    /**
     * list转化map为简单对象并追加rankNo 以及附带增率长字段
     *
     * @param data
     * @param key
     * @param orgNameKey
     * @return
     */
    public static List<Map<String, Object>> transForSampleDataWithIncre(List data, String key, String orgNameKey,
                                                                        String increaseKey) {

        List<Map<String, Object>> dataList = new ArrayList<>();
        Integer rankNo = 0;
        Object lastVObj = new Object();
        for (int i = 0; i < data.size(); i++) {
            Object d = data.get(i);

            Map<String, Object> m = new HashMap<>();

            Object fieldValue = BeanMapUtils.getValue(d, key);

            Object orgName = BeanMapUtils.getValue(d, orgNameKey);

            Object increase = BeanMapUtils.getValue(d, increaseKey);

            if (!lastVObj.equals(fieldValue)) {
                rankNo = i + 1;
            }
            m.put("rankNo", rankNo);
            m.put("fieldValue", fieldValue);
            m.put("orgName", orgName);
            m.put("increase", increase);
            lastVObj = fieldValue;
            dataList.add(m);
        }
        return dataList;
    }

    /**
     * 功能描述: 追加排名
     *
     * @param data
     * @param key
     * @return java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @author zkj
     * @date 2021/11/26
     */

    public static List<Map<String, Object>> appendRankNoToListMap(List<Map<String, Object>> data, String key) {
        Integer rankNo = 0;
        Object lastVObj = new Object();

        for (int i = 0; i < data.size(); i++) {
            Map<String, Object> d = data.get(i);

            Object fieldValue = d.get(key) == null ? "-99999999" : d.get(key);
            if (!lastVObj.equals(fieldValue)) {
                rankNo = i + 1;
            }
            d.put("rankNo", rankNo);

            lastVObj = fieldValue;
        }
        return data;
    }


    /**
     * 功能描述: list制定字段排序
     *
     * @param dataList
     * @param varField
     * @param cls
     * @return void
     * @author zkj
     * @date 2021/11/27
     */
    public static void sortListObj(List dataList, String varField, Class cls) {

        Boolean isNumeric = BeanMapUtils.isNumeric(cls, varField);
        /**
         * 倒排
         */
        dataList.sort((a, b) -> {

            Object bObj = BeanMapUtils.getValue(b, varField);
            Object aObj = BeanMapUtils.getValue(a, varField);
            if (isNumeric) {
                BigDecimal b_value = new BigDecimal("0");
                BigDecimal a_value = new BigDecimal("0");
                /**
                 * 数值类型的值转换成BigDecimal 比较倒排
                 */

                if (Objects.nonNull(bObj)) {
                    b_value = new BigDecimal(bObj.toString());
                }
                if (Objects.nonNull(aObj)) {
                    a_value = new BigDecimal(aObj.toString());
                }
                return b_value.compareTo(a_value);
            } else {
                /**
                 * 其他类型的值暂时不排序
                 */
                return 0;
            }
        });
    }

    ;

    /**
     * 功能描述: 排序字段是否未数值型
     *
     * @param dataList
     * @param varField
     * @param isNumeric
     * @return void
     * @author zkj
     * @date 2021/11/27
     */

    public static void sortListMap(List<Map<String, Object>> dataList, String varField, Boolean isNumeric) {

        /**
         * 倒排
         */
        dataList.sort((a, b) -> {

            if (a.containsKey(varField)) {
                Object bObj = b.get(varField);
                Object aObj = a.get(varField);

                if (isNumeric) {
                    /**
                     * 数值类型的值转换成BigDecimal 比较倒排
                     */
                    BigDecimal b_value = new BigDecimal("0");
                    BigDecimal a_value = new BigDecimal("0");

                    if (Objects.nonNull(bObj)) {
                        b_value = new BigDecimal(bObj.toString());
                    }
                    if (Objects.nonNull(aObj)) {
                        a_value = new BigDecimal(aObj.toString());
                    }
                    return b_value.compareTo(a_value);
                } else {
                    /**
                     * 其他类型的值暂时不排序
                     */
                    return 0;
                }
            } else {
                return 0;
            }

        });
    }

    ;

    public static void cleanNull(List dataList, String varField) {
        /**
         * 去除空值字段
         */
        List data = new ArrayList();

        dataList.forEach(e -> {
            if (e instanceof Map) {
                Object valueObj = ((Map<?, ?>) e).get(varField);
                if (Objects.nonNull(valueObj)) {
                    data.add(e);
                }
            } else {
                Object valueObj = BeanMapUtils.getValue(e, varField);
                if (Objects.nonNull(valueObj)) {
                    data.add(e);
                }
            }

        });
        dataList = data;

    }


    public static Map<String, Object> transForObject(Map<String, Object> map, Class cls) {
        Map<String, Object> data = new HashMap<>();

        try {

            if (map != null && !map.isEmpty()) {

                Map<String, BeanFieldVo> fieldMap = getField(cls);

                fieldMap.forEach((k, v) -> {
                    /**
                     * key 是中文
                     */
                    String fieldName = fieldMap.get(k).getName();
                    Class fieldClass = fieldMap.get(k).getCls();

                    boolean isTable = fieldMap.get(k).isTable;

                    Object value = map.get(k);
                    if (Objects.nonNull(value)) {
                        if(!isTable){
                            if(String.class.equals(fieldClass)){
                                data.put(fieldName, value.toString());
                            }else {
                                if (value instanceof String
                                        || value instanceof Integer
                                        || value instanceof Double
                                ) {
                                    data.put(fieldName, value);
                                } else if (value instanceof List) {

                                    List<Map<String, Object>> list = new ArrayList<>();
                                    List<Map<String, Object>> listData = (List<Map<String, Object>>) value;
                                    if (!listData.isEmpty()) {
                                        listData.forEach(l -> {
                                            Map<String, Object> d = transForObject(l, fieldClass);
                                            list.add(d);
                                        });
                                    }
                                    data.put(fieldName, list);

                                } else {
                                    Map<String, Object> dmap = (Map<String, Object>) value;

                                    Map<String, Object> d = transForObject(dmap, fieldClass);
                                    data.put(fieldName, d);
                                }
                            }

                        }else {
                            if(value instanceof JSONObject){
                                List<Map<String, Object>> list = new ArrayList<>();

                                JSONObject jsonObject = (JSONObject)value;
                                JSONObject dataObject = jsonObject.getJSONObject("data");
                                TableData tableData = dataObject.toJavaObject(TableData.class);

                                List<Map<String, Object>> listData =tableData.getListData();
                                if (!listData.isEmpty()) {
                                    listData.forEach(l -> {
                                        Map<String, Object> d = transForObject(l, fieldClass);
                                        list.add(d);
                                    });
                                }
                                data.put(fieldName, list);

                            }
                        }

                    }
                });
            }

        } catch (Exception var12) {
            var12.printStackTrace();
        }
        return data;
    }

    public static Map<String, BeanFieldVo> getField(Class cls) {

        Map<String, BeanFieldVo> fieldMap = new HashMap<>();

        Field[] fields = cls.getDeclaredFields();
        int field_size = fields.length;

        for (int i = 0; i < field_size; i++) {

            Field f = fields[i];
            String fieldName = f.getName();
            BeanField beanField = f.getAnnotation(BeanField.class);

            String value = "";
            boolean isTable = false;
            String alias = "";
            Class fieldClass = Objects.class;
            if (Objects.isNull(beanField)) {
                value = f.getName();
            } else {
                value = beanField.value();
                isTable = beanField.isTable();
                fieldClass = beanField.cls();
                 alias = beanField.alias();
            }
            if(alias!=null && !"".equals(alias)){
                BeanFieldVo fieldVo = new BeanFieldVo(fieldName, fieldClass, isTable);
                fieldMap.put(alias,fieldVo);
            }
            if (value != null && !"".equals(value)) {
                BeanFieldVo fieldVo = new BeanFieldVo(fieldName, fieldClass, isTable);
                fieldMap.put(value, fieldVo);
            }
        }
        return fieldMap;
    }
}
